@bendyline/squisq-editor-react 2.13.5 → 2.13.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-SINLDQ63.js → chunk-4MBH7MMU.js} +1 -1
- package/dist/{chunk-JMZ7RALZ.js → chunk-LDU3AWER.js} +2 -2
- package/dist/{chunk-OMSRCHQ4.js → chunk-PCIVTLQG.js} +1 -1
- package/dist/{chunk-WEEHXZUY.js → chunk-WZONLKTC.js} +404 -31
- package/dist/{chunk-V7HUUMMB.js → chunk-ZLKINE4Y.js} +97 -45
- package/dist/index.js +5 -5
- package/dist/json-editor/index.js +3 -3
- package/dist/review/index.js +2 -2
- package/dist/shell/index.js +4 -4
- package/dist/styles/index.css +4 -0
- package/package.json +6 -6
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
AlignedTableHeader,
|
|
4
4
|
MarkdownEscape,
|
|
5
5
|
PlainTextClipboard
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4MBH7MMU.js";
|
|
7
7
|
import {
|
|
8
8
|
markdownToTiptap,
|
|
9
9
|
tiptapToMarkdown
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZLKINE4Y.js";
|
|
11
11
|
|
|
12
12
|
// src/jsonEditor/JsonEditorContext.tsx
|
|
13
13
|
import { createContext, useContext, useEffect, useMemo } from "react";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
useDictationState,
|
|
20
20
|
useEditorContext,
|
|
21
21
|
useEditorContextOptional
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-PCIVTLQG.js";
|
|
23
23
|
import {
|
|
24
24
|
monacoLanguageRequestKey,
|
|
25
25
|
monacoLanguagesForDocument,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
AlignedTableHeader,
|
|
31
31
|
MarkdownEscape,
|
|
32
32
|
PlainTextClipboard
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-4MBH7MMU.js";
|
|
34
34
|
import {
|
|
35
35
|
escapeLinkLabel,
|
|
36
36
|
formatLinkDestination,
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
mediaEditNodeAttributeName,
|
|
40
40
|
mediaEditNodeAttributes,
|
|
41
41
|
tiptapToMarkdown
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-ZLKINE4Y.js";
|
|
43
43
|
import {
|
|
44
44
|
ImageEditor,
|
|
45
45
|
ImageViewer,
|
|
@@ -21814,6 +21814,10 @@ ${TASK_LIST_MARKDOWN}
|
|
|
21814
21814
|
const showBlockSectionInOverflow = showTemplateInOverflow || showTransitionInOverflow;
|
|
21815
21815
|
const overflowBlockLabel = currentTemplate ? templateLabel(currentTemplate) : "Heading";
|
|
21816
21816
|
const showToolbarOverflow = actionsLaneShown && (collapsedFormatButtons.length > 0 || showFormattingControls && clippedContextual.size > 0 || showInsertInOverflow || collapsedChrome.length > 0);
|
|
21817
|
+
const portalDialog = (dialog) => createPortal13(
|
|
21818
|
+
/* @__PURE__ */ jsx50("div", { className: "squisq-dialog-portal", "data-theme": colorScheme, children: dialog }),
|
|
21819
|
+
document.body
|
|
21820
|
+
);
|
|
21817
21821
|
return /* @__PURE__ */ jsxs39(
|
|
21818
21822
|
"div",
|
|
21819
21823
|
{
|
|
@@ -22440,35 +22444,39 @@ ${TASK_LIST_MARKDOWN}
|
|
|
22440
22444
|
}
|
|
22441
22445
|
),
|
|
22442
22446
|
slotRight,
|
|
22443
|
-
showDocumentChrome && showDocSettings &&
|
|
22444
|
-
|
|
22445
|
-
|
|
22446
|
-
|
|
22447
|
-
|
|
22448
|
-
|
|
22449
|
-
|
|
22450
|
-
|
|
22451
|
-
|
|
22452
|
-
|
|
22453
|
-
|
|
22454
|
-
|
|
22447
|
+
showDocumentChrome && showDocSettings && portalDialog(
|
|
22448
|
+
/* @__PURE__ */ jsx50(
|
|
22449
|
+
DocumentSettingsDialog,
|
|
22450
|
+
{
|
|
22451
|
+
markdownSource,
|
|
22452
|
+
onSave: (next) => {
|
|
22453
|
+
setMarkdownSource(next);
|
|
22454
|
+
setShowDocSettings(false);
|
|
22455
|
+
},
|
|
22456
|
+
onClose: () => setShowDocSettings(false),
|
|
22457
|
+
defaultThemeId: previewSettings?.inheritedThemeId,
|
|
22458
|
+
defaultThemeLabel: previewSettings?.inheritedThemeLabel
|
|
22459
|
+
}
|
|
22460
|
+
)
|
|
22455
22461
|
),
|
|
22456
22462
|
showDocumentChrome && showLayoutManager && /* @__PURE__ */ jsx50(CustomLayoutManager, { onClose: () => setShowLayoutManager(false) }),
|
|
22457
22463
|
contextMenuAvailable && /* @__PURE__ */ jsx50(WikiLinkMenuItems, { onEdit: () => handleAction("link") }),
|
|
22458
|
-
linkDialog &&
|
|
22459
|
-
|
|
22460
|
-
|
|
22461
|
-
|
|
22462
|
-
|
|
22463
|
-
|
|
22464
|
-
|
|
22465
|
-
|
|
22466
|
-
|
|
22467
|
-
|
|
22468
|
-
|
|
22469
|
-
|
|
22464
|
+
linkDialog && portalDialog(
|
|
22465
|
+
/* @__PURE__ */ jsx50(
|
|
22466
|
+
LinkDialog,
|
|
22467
|
+
{
|
|
22468
|
+
mode: linkDialog.mode,
|
|
22469
|
+
kind: linkDialog.wiki ? "wiki" : "url",
|
|
22470
|
+
initialText: linkDialog.initialText,
|
|
22471
|
+
initialUrl: linkDialog.initialUrl,
|
|
22472
|
+
onConfirm: handleLinkConfirm,
|
|
22473
|
+
onClose: () => setLinkDialog(null),
|
|
22474
|
+
documentLinkProvider,
|
|
22475
|
+
linkSchemes
|
|
22476
|
+
}
|
|
22477
|
+
)
|
|
22470
22478
|
),
|
|
22471
|
-
videoEmbedDialog,
|
|
22479
|
+
videoEmbedDialog && portalDialog(videoEmbedDialog),
|
|
22472
22480
|
insertMenuAnchor && createPortal13(
|
|
22473
22481
|
/* @__PURE__ */ jsxs39(
|
|
22474
22482
|
"div",
|
|
@@ -33903,10 +33911,41 @@ function persistFromWrite(bodyMd, state) {
|
|
|
33903
33911
|
import { useCallback as useCallback43, useEffect as useEffect54, useMemo as useMemo41, useRef as useRef50, useState as useState67 } from "react";
|
|
33904
33912
|
import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
|
|
33905
33913
|
import { Selection as Selection2 } from "@tiptap/pm/state";
|
|
33906
|
-
import { Extension as
|
|
33914
|
+
import { Extension as Extension17, getHTMLFromFragment } from "@tiptap/core";
|
|
33907
33915
|
import StarterKit2 from "@tiptap/starter-kit";
|
|
33908
33916
|
import Table from "@tiptap/extension-table";
|
|
33909
33917
|
import TableRow from "@tiptap/extension-table-row";
|
|
33918
|
+
|
|
33919
|
+
// src/tiptap/codeFenceSource.ts
|
|
33920
|
+
import { Extension as Extension16 } from "@tiptap/core";
|
|
33921
|
+
var FENCE_MARKER = /^(`{3,}|~{3,})$/;
|
|
33922
|
+
var CodeFenceSource = Extension16.create({
|
|
33923
|
+
name: "codeFenceSource",
|
|
33924
|
+
addGlobalAttributes() {
|
|
33925
|
+
return [
|
|
33926
|
+
{
|
|
33927
|
+
types: ["codeBlock"],
|
|
33928
|
+
attributes: {
|
|
33929
|
+
fenceMarker: {
|
|
33930
|
+
default: null,
|
|
33931
|
+
parseHTML: (element) => {
|
|
33932
|
+
const value = element.getAttribute("data-squisq-fence");
|
|
33933
|
+
return value && FENCE_MARKER.test(value) ? value : null;
|
|
33934
|
+
},
|
|
33935
|
+
renderHTML: (attributes) => typeof attributes.fenceMarker === "string" && FENCE_MARKER.test(attributes.fenceMarker) ? { "data-squisq-fence": attributes.fenceMarker } : {}
|
|
33936
|
+
},
|
|
33937
|
+
fenceMeta: {
|
|
33938
|
+
default: null,
|
|
33939
|
+
parseHTML: (element) => element.getAttribute("data-squisq-fence-meta") || null,
|
|
33940
|
+
renderHTML: (attributes) => typeof attributes.fenceMeta === "string" && attributes.fenceMeta ? { "data-squisq-fence-meta": attributes.fenceMeta } : {}
|
|
33941
|
+
}
|
|
33942
|
+
}
|
|
33943
|
+
}
|
|
33944
|
+
];
|
|
33945
|
+
}
|
|
33946
|
+
});
|
|
33947
|
+
|
|
33948
|
+
// src/WysiwygEditor.tsx
|
|
33910
33949
|
import TaskList from "@tiptap/extension-task-list";
|
|
33911
33950
|
import TaskItem from "@tiptap/extension-task-item";
|
|
33912
33951
|
import Link2 from "@tiptap/extension-link";
|
|
@@ -34549,6 +34588,15 @@ var ImageWithMediaProvider = Image.extend({
|
|
|
34549
34588
|
return Number.isFinite(n) && n > 0 ? n : null;
|
|
34550
34589
|
},
|
|
34551
34590
|
renderHTML: (attrs) => attrs.height ? { height: String(attrs.height) } : {}
|
|
34591
|
+
},
|
|
34592
|
+
// A linked image (`[](url)`, a README badge). This image is
|
|
34593
|
+
// a block node, which a link mark cannot wrap, so the parser lifts it
|
|
34594
|
+
// out of its `<a>` and the link was lost on every save. Keep the target
|
|
34595
|
+
// as an attribute the Markdown bridge writes back around the image.
|
|
34596
|
+
href: {
|
|
34597
|
+
default: null,
|
|
34598
|
+
parseHTML: (element) => element.getAttribute("data-squisq-image-href") ?? element.closest("a[href]")?.getAttribute("href") ?? null,
|
|
34599
|
+
renderHTML: (attrs) => attrs.href ? { "data-squisq-image-href": attrs.href } : {}
|
|
34552
34600
|
}
|
|
34553
34601
|
};
|
|
34554
34602
|
},
|
|
@@ -35127,6 +35175,316 @@ function DocumentTray({ editor }) {
|
|
|
35127
35175
|
// src/WysiwygEditor.tsx
|
|
35128
35176
|
import { profileBlockContents as profileBlockContents2, recommendTemplatesForBlock as recommendTemplatesForBlock2 } from "@bendyline/squisq/recommend";
|
|
35129
35177
|
|
|
35178
|
+
// src/sourcePreservation.ts
|
|
35179
|
+
function pairLines(a, b) {
|
|
35180
|
+
const aToB = new Int32Array(a.length).fill(-1);
|
|
35181
|
+
const work = [[0, a.length, 0, b.length]];
|
|
35182
|
+
while (work.length > 0) {
|
|
35183
|
+
let [aLo, aHi, bLo, bHi] = work.pop();
|
|
35184
|
+
while (aLo < aHi && bLo < bHi && a[aLo] === b[bLo]) aToB[aLo++] = bLo++;
|
|
35185
|
+
while (aHi > aLo && bHi > bLo && a[aHi - 1] === b[bHi - 1]) aToB[--aHi] = --bHi;
|
|
35186
|
+
if (aLo >= aHi || bLo >= bHi) continue;
|
|
35187
|
+
const countA = /* @__PURE__ */ new Map();
|
|
35188
|
+
const indexA = /* @__PURE__ */ new Map();
|
|
35189
|
+
for (let i = aLo; i < aHi; i++) {
|
|
35190
|
+
const line = a[i];
|
|
35191
|
+
if (line.trim() === "") continue;
|
|
35192
|
+
countA.set(line, (countA.get(line) ?? 0) + 1);
|
|
35193
|
+
indexA.set(line, i);
|
|
35194
|
+
}
|
|
35195
|
+
const countB = /* @__PURE__ */ new Map();
|
|
35196
|
+
for (let j = bLo; j < bHi; j++) {
|
|
35197
|
+
const line = b[j];
|
|
35198
|
+
if (countA.has(line)) countB.set(line, (countB.get(line) ?? 0) + 1);
|
|
35199
|
+
}
|
|
35200
|
+
const candidates = [];
|
|
35201
|
+
for (let j = bLo; j < bHi; j++) {
|
|
35202
|
+
const line = b[j];
|
|
35203
|
+
if (countB.get(line) === 1 && countA.get(line) === 1) {
|
|
35204
|
+
candidates.push([indexA.get(line), j]);
|
|
35205
|
+
}
|
|
35206
|
+
}
|
|
35207
|
+
const anchors = longestIncreasingByA(candidates);
|
|
35208
|
+
if (anchors.length === 0) continue;
|
|
35209
|
+
let prevA = aLo;
|
|
35210
|
+
let prevB = bLo;
|
|
35211
|
+
for (const [i, j] of anchors) {
|
|
35212
|
+
aToB[i] = j;
|
|
35213
|
+
work.push([prevA, i, prevB, j]);
|
|
35214
|
+
prevA = i + 1;
|
|
35215
|
+
prevB = j + 1;
|
|
35216
|
+
}
|
|
35217
|
+
work.push([prevA, aHi, prevB, bHi]);
|
|
35218
|
+
}
|
|
35219
|
+
return aToB;
|
|
35220
|
+
}
|
|
35221
|
+
function longestIncreasingByA(pairs) {
|
|
35222
|
+
if (pairs.length === 0) return [];
|
|
35223
|
+
const tails = [];
|
|
35224
|
+
const previous = new Int32Array(pairs.length).fill(-1);
|
|
35225
|
+
for (let p = 0; p < pairs.length; p++) {
|
|
35226
|
+
const value = pairs[p][0];
|
|
35227
|
+
let lo = 0;
|
|
35228
|
+
let hi = tails.length;
|
|
35229
|
+
while (lo < hi) {
|
|
35230
|
+
const mid = lo + hi >> 1;
|
|
35231
|
+
if (pairs[tails[mid]][0] < value) lo = mid + 1;
|
|
35232
|
+
else hi = mid;
|
|
35233
|
+
}
|
|
35234
|
+
if (lo > 0) previous[p] = tails[lo - 1];
|
|
35235
|
+
tails[lo] = p;
|
|
35236
|
+
}
|
|
35237
|
+
const result = [];
|
|
35238
|
+
for (let p = tails[tails.length - 1]; p >= 0; p = previous[p]) result.push(pairs[p]);
|
|
35239
|
+
return result.reverse();
|
|
35240
|
+
}
|
|
35241
|
+
function lineKeys(lines2) {
|
|
35242
|
+
return lines2.map((line) => line.endsWith("\r") ? line.slice(0, -1) : line);
|
|
35243
|
+
}
|
|
35244
|
+
function detectLineEnding(text) {
|
|
35245
|
+
const breaks = text.split("\n").length - 1;
|
|
35246
|
+
if (breaks === 0) return "\n";
|
|
35247
|
+
const crlf = text.split("\r\n").length - 1;
|
|
35248
|
+
return crlf * 2 > breaks ? "\r\n" : "\n";
|
|
35249
|
+
}
|
|
35250
|
+
function blocksIn(lines2, roles, start, end) {
|
|
35251
|
+
const blocks = [];
|
|
35252
|
+
let blockStart = -1;
|
|
35253
|
+
for (let i = start; i < end; i++) {
|
|
35254
|
+
const separator = lines2[i].trim() === "" && roles[i] === "out";
|
|
35255
|
+
if (separator) {
|
|
35256
|
+
if (blockStart >= 0) blocks.push([blockStart, i]);
|
|
35257
|
+
blockStart = -1;
|
|
35258
|
+
} else if (blockStart < 0) {
|
|
35259
|
+
blockStart = i;
|
|
35260
|
+
}
|
|
35261
|
+
}
|
|
35262
|
+
if (blockStart >= 0) blocks.push([blockStart, end]);
|
|
35263
|
+
return blocks;
|
|
35264
|
+
}
|
|
35265
|
+
function blockText(lines2, [start, end]) {
|
|
35266
|
+
return lines2.slice(start, end).join("\n").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "");
|
|
35267
|
+
}
|
|
35268
|
+
function refineGap(regions, s, n, sStart, sEnd, nStart, nEnd) {
|
|
35269
|
+
const sBlocks = blocksIn(s.lines, s.roles, sStart, sEnd);
|
|
35270
|
+
const nBlocks = blocksIn(n.lines, n.roles, nStart, nEnd);
|
|
35271
|
+
const same = (a, b) => {
|
|
35272
|
+
const text = blockText(s.lines, a);
|
|
35273
|
+
return text !== "" && text === blockText(n.lines, b);
|
|
35274
|
+
};
|
|
35275
|
+
let head = 0;
|
|
35276
|
+
while (head < sBlocks.length && head < nBlocks.length && same(sBlocks[head], nBlocks[head])) {
|
|
35277
|
+
head++;
|
|
35278
|
+
}
|
|
35279
|
+
let tail = 0;
|
|
35280
|
+
while (tail < sBlocks.length - head && tail < nBlocks.length - head && same(sBlocks[sBlocks.length - 1 - tail], nBlocks[nBlocks.length - 1 - tail])) {
|
|
35281
|
+
tail++;
|
|
35282
|
+
}
|
|
35283
|
+
let sAt = sStart;
|
|
35284
|
+
let nAt = nStart;
|
|
35285
|
+
const push = (sTo, nTo) => {
|
|
35286
|
+
if (sTo > sAt || nTo > nAt) regions.push({ sStart: sAt, sEnd: sTo, nStart: nAt, nEnd: nTo });
|
|
35287
|
+
sAt = sTo;
|
|
35288
|
+
nAt = nTo;
|
|
35289
|
+
};
|
|
35290
|
+
const pairs = [];
|
|
35291
|
+
for (let k2 = 0; k2 < head; k2++) pairs.push([sBlocks[k2], nBlocks[k2]]);
|
|
35292
|
+
const middleS = head < sBlocks.length - tail ? sBlocks[head][0] : null;
|
|
35293
|
+
const middleN = head < nBlocks.length - tail ? nBlocks[head][0] : null;
|
|
35294
|
+
for (const [sBlock, nBlock] of pairs) {
|
|
35295
|
+
push(sBlock[0], nBlock[0]);
|
|
35296
|
+
push(sBlock[1], nBlock[1]);
|
|
35297
|
+
}
|
|
35298
|
+
if (middleS !== null || middleN !== null) {
|
|
35299
|
+
const sTo = tail > 0 ? sBlocks[sBlocks.length - tail][0] : sEnd;
|
|
35300
|
+
const nTo = tail > 0 ? nBlocks[nBlocks.length - tail][0] : nEnd;
|
|
35301
|
+
push(sTo, nTo);
|
|
35302
|
+
}
|
|
35303
|
+
for (let k2 = tail; k2 > 0; k2--) {
|
|
35304
|
+
const sBlock = sBlocks[sBlocks.length - k2];
|
|
35305
|
+
const nBlock = nBlocks[nBlocks.length - k2];
|
|
35306
|
+
push(sBlock[0], nBlock[0]);
|
|
35307
|
+
push(sBlock[1], nBlock[1]);
|
|
35308
|
+
}
|
|
35309
|
+
push(sEnd, nEnd);
|
|
35310
|
+
}
|
|
35311
|
+
function createSourceBaseline(original, normalized) {
|
|
35312
|
+
const originalLines = original.split("\n");
|
|
35313
|
+
const normalizedLines = normalized.split("\n");
|
|
35314
|
+
const originalRoles = literalRoles(originalLines);
|
|
35315
|
+
const sides = {
|
|
35316
|
+
s: { lines: originalLines, roles: originalRoles },
|
|
35317
|
+
n: { lines: normalizedLines, roles: literalRoles(normalizedLines) }
|
|
35318
|
+
};
|
|
35319
|
+
const sToN = pairLines(lineKeys(originalLines), lineKeys(normalizedLines));
|
|
35320
|
+
const regions = [];
|
|
35321
|
+
let s = 0;
|
|
35322
|
+
let n = 0;
|
|
35323
|
+
const pushGap = (sEnd, nEnd) => {
|
|
35324
|
+
if (sEnd > s || nEnd > n) refineGap(regions, sides.s, sides.n, s, sEnd, n, nEnd);
|
|
35325
|
+
};
|
|
35326
|
+
for (let i = 0; i < originalLines.length; i++) {
|
|
35327
|
+
const j = sToN[i];
|
|
35328
|
+
if (j < 0) continue;
|
|
35329
|
+
pushGap(i, j);
|
|
35330
|
+
regions.push({ sStart: i, sEnd: i + 1, nStart: j, nEnd: j + 1 });
|
|
35331
|
+
s = i + 1;
|
|
35332
|
+
n = j + 1;
|
|
35333
|
+
}
|
|
35334
|
+
pushGap(originalLines.length, normalizedLines.length);
|
|
35335
|
+
return {
|
|
35336
|
+
original,
|
|
35337
|
+
normalized,
|
|
35338
|
+
originalLines,
|
|
35339
|
+
normalizedLines,
|
|
35340
|
+
regions,
|
|
35341
|
+
originalRoles,
|
|
35342
|
+
lineEnding: detectLineEnding(original)
|
|
35343
|
+
};
|
|
35344
|
+
}
|
|
35345
|
+
function literalRoles(lines2) {
|
|
35346
|
+
const roles = [];
|
|
35347
|
+
let fence = null;
|
|
35348
|
+
let math = false;
|
|
35349
|
+
let comment = false;
|
|
35350
|
+
for (const raw of lines2) {
|
|
35351
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
35352
|
+
if (fence) {
|
|
35353
|
+
const close = /^ {0,3}(`{3,}|~{3,})[ \t]*$/.exec(line);
|
|
35354
|
+
if (close && close[1][0] === fence.char && close[1].length >= fence.length) {
|
|
35355
|
+
fence = null;
|
|
35356
|
+
roles.push("close");
|
|
35357
|
+
} else {
|
|
35358
|
+
roles.push("in");
|
|
35359
|
+
}
|
|
35360
|
+
continue;
|
|
35361
|
+
}
|
|
35362
|
+
if (math) {
|
|
35363
|
+
if (line.trim() === "$$") {
|
|
35364
|
+
math = false;
|
|
35365
|
+
roles.push("close");
|
|
35366
|
+
} else {
|
|
35367
|
+
roles.push("in");
|
|
35368
|
+
}
|
|
35369
|
+
continue;
|
|
35370
|
+
}
|
|
35371
|
+
if (comment) {
|
|
35372
|
+
if (line.includes("-->")) {
|
|
35373
|
+
comment = false;
|
|
35374
|
+
roles.push("close");
|
|
35375
|
+
} else {
|
|
35376
|
+
roles.push("in");
|
|
35377
|
+
}
|
|
35378
|
+
continue;
|
|
35379
|
+
}
|
|
35380
|
+
const open = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
|
|
35381
|
+
if (open && !(open[1][0] === "`" && open[2].includes("`"))) {
|
|
35382
|
+
fence = { char: open[1][0], length: open[1].length };
|
|
35383
|
+
roles.push("open");
|
|
35384
|
+
continue;
|
|
35385
|
+
}
|
|
35386
|
+
if (line.trim() === "$$") {
|
|
35387
|
+
math = true;
|
|
35388
|
+
roles.push("open");
|
|
35389
|
+
continue;
|
|
35390
|
+
}
|
|
35391
|
+
const commentStart = line.indexOf("<!--");
|
|
35392
|
+
if (commentStart >= 0 && !line.includes("-->", commentStart + 4)) {
|
|
35393
|
+
comment = true;
|
|
35394
|
+
roles.push("open");
|
|
35395
|
+
continue;
|
|
35396
|
+
}
|
|
35397
|
+
roles.push("out");
|
|
35398
|
+
}
|
|
35399
|
+
return roles;
|
|
35400
|
+
}
|
|
35401
|
+
function preserveSource(baseline, edited) {
|
|
35402
|
+
if (baseline.original === baseline.normalized) return edited;
|
|
35403
|
+
if (edited === baseline.normalized) return baseline.original;
|
|
35404
|
+
const editedLines = edited.split("\n");
|
|
35405
|
+
const nToM = pairLines(lineKeys(baseline.normalizedLines), lineKeys(editedLines));
|
|
35406
|
+
const { regions } = baseline;
|
|
35407
|
+
const clean = new Array(regions.length);
|
|
35408
|
+
const mStart = new Int32Array(regions.length);
|
|
35409
|
+
const mEnd = new Int32Array(regions.length);
|
|
35410
|
+
for (let r = 0; r < regions.length; r++) {
|
|
35411
|
+
const region = regions[r];
|
|
35412
|
+
if (region.nEnd === region.nStart) {
|
|
35413
|
+
clean[r] = false;
|
|
35414
|
+
continue;
|
|
35415
|
+
}
|
|
35416
|
+
let ok = true;
|
|
35417
|
+
const first = nToM[region.nStart];
|
|
35418
|
+
for (let k2 = region.nStart; k2 < region.nEnd && ok; k2++) {
|
|
35419
|
+
ok = nToM[k2] === first + (k2 - region.nStart) && first >= 0;
|
|
35420
|
+
}
|
|
35421
|
+
clean[r] = ok;
|
|
35422
|
+
mStart[r] = first;
|
|
35423
|
+
mEnd[r] = first + (region.nEnd - region.nStart);
|
|
35424
|
+
}
|
|
35425
|
+
const isBlank2 = (lines2, start, end) => {
|
|
35426
|
+
for (let k2 = start; k2 < end; k2++) if (lines2[k2].trim() !== "") return false;
|
|
35427
|
+
return true;
|
|
35428
|
+
};
|
|
35429
|
+
const separatorIsSafe = regions.map((region, r) => {
|
|
35430
|
+
if (region.nEnd === region.nStart) return true;
|
|
35431
|
+
if (!isBlank2(baseline.normalizedLines, region.nStart, region.nEnd)) return true;
|
|
35432
|
+
if (!isBlank2(baseline.originalLines, region.sStart, region.sEnd)) return true;
|
|
35433
|
+
const neighbourClean = (k2) => k2 < 0 || k2 >= regions.length || regions[k2].nEnd === regions[k2].nStart || clean[k2];
|
|
35434
|
+
return neighbourClean(r - 1) && neighbourClean(r + 1);
|
|
35435
|
+
});
|
|
35436
|
+
for (let r = 0; r < regions.length; r++) if (!separatorIsSafe[r]) clean[r] = false;
|
|
35437
|
+
for (let r = 0; r < regions.length; r++) {
|
|
35438
|
+
const region = regions[r];
|
|
35439
|
+
if (region.nEnd !== region.nStart) continue;
|
|
35440
|
+
const before = r - 1;
|
|
35441
|
+
const after = r + 1;
|
|
35442
|
+
let position = -1;
|
|
35443
|
+
if (before < 0) position = 0;
|
|
35444
|
+
else if (clean[before]) position = mEnd[before];
|
|
35445
|
+
else if (after >= regions.length) position = editedLines.length;
|
|
35446
|
+
else if (clean[after]) position = mStart[after];
|
|
35447
|
+
clean[r] = position >= 0;
|
|
35448
|
+
mStart[r] = mEnd[r] = position;
|
|
35449
|
+
}
|
|
35450
|
+
const out = [];
|
|
35451
|
+
const needsLineEnding = [];
|
|
35452
|
+
const sourceRole = [];
|
|
35453
|
+
const lastOriginal = baseline.originalLines.length - 1;
|
|
35454
|
+
const editedRoles = literalRoles(editedLines);
|
|
35455
|
+
let cursor = 0;
|
|
35456
|
+
const emitEdited = (end) => {
|
|
35457
|
+
for (; cursor < end; cursor++) {
|
|
35458
|
+
out.push(editedLines[cursor]);
|
|
35459
|
+
needsLineEnding.push(true);
|
|
35460
|
+
sourceRole.push(editedRoles[cursor]);
|
|
35461
|
+
}
|
|
35462
|
+
};
|
|
35463
|
+
for (let r = 0; r < regions.length; r++) {
|
|
35464
|
+
if (!clean[r]) continue;
|
|
35465
|
+
const region = regions[r];
|
|
35466
|
+
if (mStart[r] < cursor) return edited;
|
|
35467
|
+
emitEdited(mStart[r]);
|
|
35468
|
+
for (let k2 = region.sStart; k2 < region.sEnd; k2++) {
|
|
35469
|
+
out.push(baseline.originalLines[k2]);
|
|
35470
|
+
needsLineEnding.push(k2 === lastOriginal);
|
|
35471
|
+
sourceRole.push(baseline.originalRoles[k2]);
|
|
35472
|
+
}
|
|
35473
|
+
cursor = mEnd[r];
|
|
35474
|
+
}
|
|
35475
|
+
emitEdited(editedLines.length);
|
|
35476
|
+
const assembledRoles = literalRoles(out);
|
|
35477
|
+
for (let k2 = 0; k2 < out.length; k2++) {
|
|
35478
|
+
if (assembledRoles[k2] !== sourceRole[k2]) return edited;
|
|
35479
|
+
}
|
|
35480
|
+
if (baseline.lineEnding === "\r\n") {
|
|
35481
|
+
for (let k2 = 0; k2 < out.length - 1; k2++) {
|
|
35482
|
+
if (needsLineEnding[k2] && !out[k2].endsWith("\r")) out[k2] += "\r";
|
|
35483
|
+
}
|
|
35484
|
+
}
|
|
35485
|
+
return out.join("\n");
|
|
35486
|
+
}
|
|
35487
|
+
|
|
35130
35488
|
// src/MentionExtension.tsx
|
|
35131
35489
|
import Mention from "@tiptap/extension-mention";
|
|
35132
35490
|
import { PluginKey as PluginKey17 } from "@tiptap/pm/state";
|
|
@@ -35621,7 +35979,7 @@ var BLOCK_TAG_DATA_VALUES = {
|
|
|
35621
35979
|
function pickEmptyPrompt() {
|
|
35622
35980
|
return EMPTY_PROMPTS[Math.floor(Math.random() * EMPTY_PROMPTS.length)];
|
|
35623
35981
|
}
|
|
35624
|
-
var SourceFrontmatter =
|
|
35982
|
+
var SourceFrontmatter = Extension17.create({
|
|
35625
35983
|
name: "sourceFrontmatter",
|
|
35626
35984
|
addOptions() {
|
|
35627
35985
|
return { initial: "" };
|
|
@@ -35781,6 +36139,10 @@ function WysiwygEditor({
|
|
|
35781
36139
|
initialDisplayBodyRef.current = body;
|
|
35782
36140
|
}
|
|
35783
36141
|
}
|
|
36142
|
+
const loadedSourceRef = useRef50(null);
|
|
36143
|
+
if (loadedSourceRef.current === null) {
|
|
36144
|
+
loadedSourceRef.current = { body: stripFrontmatter(editorSource).body, baseline: null };
|
|
36145
|
+
}
|
|
35784
36146
|
const initialContentRef = useRef50(void 0);
|
|
35785
36147
|
if (initialContentRef.current === void 0) {
|
|
35786
36148
|
initialContentRef.current = markdownToTiptap(initialDisplayBodyRef.current);
|
|
@@ -35807,6 +36169,7 @@ function WysiwygEditor({
|
|
|
35807
36169
|
}
|
|
35808
36170
|
}),
|
|
35809
36171
|
HeadingWithTemplate.configure({ levels: [1, 2, 3, 4, 5, 6] }),
|
|
36172
|
+
CodeFenceSource,
|
|
35810
36173
|
Superscript,
|
|
35811
36174
|
Subscript,
|
|
35812
36175
|
MarkdownEscape,
|
|
@@ -35865,7 +36228,16 @@ function WysiwygEditor({
|
|
|
35865
36228
|
onUpdate: ({ editor: ed, transaction }) => {
|
|
35866
36229
|
if (!transaction.docChanged) return;
|
|
35867
36230
|
if (isExternalUpdate.current || externalApplyPendingRef.current) return;
|
|
35868
|
-
const
|
|
36231
|
+
const serialize = (html) => persistFromWrite(tiptapToMarkdown(html), wrapStateRef.current);
|
|
36232
|
+
let bodyMd = serialize(ed.getHTML());
|
|
36233
|
+
const loaded = loadedSourceRef.current;
|
|
36234
|
+
if (loaded) {
|
|
36235
|
+
loaded.baseline ?? (loaded.baseline = createSourceBaseline(
|
|
36236
|
+
loaded.body,
|
|
36237
|
+
serialize(getHTMLFromFragment(transaction.before.content, ed.schema))
|
|
36238
|
+
));
|
|
36239
|
+
bodyMd = preserveSource(loaded.baseline, bodyMd);
|
|
36240
|
+
}
|
|
35869
36241
|
const frontmatter = sourceLayoutRef.current === "document" ? String(ed.state.doc.attrs.sourceFrontmatter ?? "") : frontmatterRef.current;
|
|
35870
36242
|
const newSource = frontmatter + bodyMd;
|
|
35871
36243
|
pendingLocalSourcesRef.current.push(newSource);
|
|
@@ -36121,6 +36493,7 @@ function WysiwygEditor({
|
|
|
36121
36493
|
const { body, frontmatter } = stripFrontmatter(editorSource);
|
|
36122
36494
|
pendingLocalSourcesRef.current = [];
|
|
36123
36495
|
frontmatterRef.current = frontmatter;
|
|
36496
|
+
loadedSourceRef.current = { body, baseline: null };
|
|
36124
36497
|
let displayBody = body;
|
|
36125
36498
|
if (wrapPolicyEnabled) {
|
|
36126
36499
|
const ingest = ingestForWrite(body);
|
|
@@ -65,6 +65,57 @@ function escapeLinkLabel(text) {
|
|
|
65
65
|
return text.replace(/([\\[\]])/g, "\\$1");
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// src/htmlEntities.ts
|
|
69
|
+
function escapeHtml(text) {
|
|
70
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
71
|
+
}
|
|
72
|
+
function unescapeHtml(text) {
|
|
73
|
+
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/ | | /gi, "\xA0").replace(/&/g, "&");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/markdownFence.ts
|
|
77
|
+
var BACKTICK = "`";
|
|
78
|
+
function matchFenceOpen(line) {
|
|
79
|
+
const match = /^( {0,3})(`{3,}|~{3,})(.*)$/.exec(line);
|
|
80
|
+
if (!match) return null;
|
|
81
|
+
const marker = match[2];
|
|
82
|
+
const info = match[3];
|
|
83
|
+
if (marker[0] === BACKTICK && info.includes(BACKTICK)) return null;
|
|
84
|
+
return { indent: match[1].length, marker, info: info.trim() };
|
|
85
|
+
}
|
|
86
|
+
function isFenceClose(line, fence) {
|
|
87
|
+
const match = /^ {0,3}(`{3,}|~{3,})[ \t]*$/.exec(line);
|
|
88
|
+
return !!match && match[1][0] === fence.marker[0] && match[1].length >= fence.marker.length;
|
|
89
|
+
}
|
|
90
|
+
function fenceContentLine(line, fence) {
|
|
91
|
+
const indent = /^ */.exec(line)[0].length;
|
|
92
|
+
return line.slice(Math.min(indent, fence.indent));
|
|
93
|
+
}
|
|
94
|
+
function fencedCodeToHtml(fence, codeLines) {
|
|
95
|
+
const [lang = "", ...rest] = fence.info.split(/\s+/);
|
|
96
|
+
const meta = rest.join(" ");
|
|
97
|
+
const langAttr = lang ? ` class="language-${escapeHtml(lang)}"` : "";
|
|
98
|
+
const markerAttr = fence.marker === "```" ? "" : ` data-squisq-fence="${fence.marker}"`;
|
|
99
|
+
const metaAttr = meta ? ` data-squisq-fence-meta="${escapeHtml(meta)}"` : "";
|
|
100
|
+
return `<pre${markerAttr}${metaAttr}><code${langAttr}>${escapeHtml(codeLines.join("\n"))}</code></pre>`;
|
|
101
|
+
}
|
|
102
|
+
function fenceForCode(code, info, preferred) {
|
|
103
|
+
const char = preferred[0] === "~" || info.includes(BACKTICK) ? "~" : BACKTICK;
|
|
104
|
+
let length = preferred[0] === char ? Math.max(3, preferred.length) : 3;
|
|
105
|
+
const runs = char === "~" ? /^ {0,3}(~{3,})/gm : /^ {0,3}(`{3,})/gm;
|
|
106
|
+
for (const run of code.matchAll(runs)) length = Math.max(length, run[1].length + 1);
|
|
107
|
+
return char.repeat(length);
|
|
108
|
+
}
|
|
109
|
+
function fencedCodeToMarkdown(preAttrs, codeAttrs, codeHtml) {
|
|
110
|
+
const lang = unescapeHtml(/\bclass="language-([^"]*)"/.exec(codeAttrs)?.[1] ?? "");
|
|
111
|
+
const marker = /\bdata-squisq-fence="([`~]{3,})"/.exec(preAttrs)?.[1] ?? "```";
|
|
112
|
+
const meta = unescapeHtml(/\bdata-squisq-fence-meta="([^"]*)"/.exec(preAttrs)?.[1] ?? "");
|
|
113
|
+
const info = meta ? `${lang} ${meta}`.trim() : lang;
|
|
114
|
+
const code = unescapeHtml(codeHtml);
|
|
115
|
+
const fence = fenceForCode(code, info, marker);
|
|
116
|
+
return [fence + info, code, fence];
|
|
117
|
+
}
|
|
118
|
+
|
|
68
119
|
// src/markdownQuote.ts
|
|
69
120
|
function isQuoteLine(line) {
|
|
70
121
|
return line.startsWith("> ") || line.trimEnd() === ">";
|
|
@@ -210,8 +261,7 @@ var RE_ESCAPE_SPAN = new RegExp(
|
|
|
210
261
|
"gi"
|
|
211
262
|
);
|
|
212
263
|
var RE_INLINE_CODE = /`(.+?)`/g;
|
|
213
|
-
var
|
|
214
|
-
var FENCE = "```";
|
|
264
|
+
var BACKTICK2 = "`";
|
|
215
265
|
var RE_IMAGE = /!\[(.*?)\]\((.+?)\)/g;
|
|
216
266
|
var RE_MENTION = /@\[([^\]]+?)\]\(([a-z][a-z0-9+.-]*)\\?:([^)\s]+)\)/gi;
|
|
217
267
|
var RE_MENTION_TAG = /<span\b[^>]*?\bdata-mention\b[^>]*?>(?:<[^>]+>)*([^<]*)<\/span>/gi;
|
|
@@ -224,17 +274,23 @@ var RE_A_TAG = /<a\b([^>]*)>(.*?)<\/a>/g;
|
|
|
224
274
|
var RE_IMG_TAG = /<img\b([^>]*)>/g;
|
|
225
275
|
var RE_STRIP_TAGS = /<[^>]+>/g;
|
|
226
276
|
function joinWrappedCodeSpans(lines) {
|
|
227
|
-
if (!lines.some((line) => line.includes(
|
|
277
|
+
if (!lines.some((line) => line.includes(BACKTICK2))) return lines;
|
|
228
278
|
const joined = [];
|
|
229
|
-
let
|
|
279
|
+
let fence = null;
|
|
230
280
|
for (let i = 0; i < lines.length; i++) {
|
|
231
281
|
const line = lines[i];
|
|
232
|
-
if (
|
|
233
|
-
|
|
282
|
+
if (fence) {
|
|
283
|
+
if (isFenceClose(line, fence)) fence = null;
|
|
234
284
|
joined.push(line);
|
|
235
285
|
continue;
|
|
236
286
|
}
|
|
237
|
-
|
|
287
|
+
const opener = matchFenceOpen(line);
|
|
288
|
+
if (opener) {
|
|
289
|
+
fence = opener;
|
|
290
|
+
joined.push(line);
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
if (!leavesCodeSpanOpen(line)) {
|
|
238
294
|
joined.push(line);
|
|
239
295
|
continue;
|
|
240
296
|
}
|
|
@@ -243,7 +299,7 @@ function joinWrappedCodeSpans(lines) {
|
|
|
243
299
|
let closed = false;
|
|
244
300
|
while (next < lines.length) {
|
|
245
301
|
const candidate = lines[next];
|
|
246
|
-
if (candidate.trim() === "" || candidate
|
|
302
|
+
if (candidate.trim() === "" || matchFenceOpen(candidate)) break;
|
|
247
303
|
merged = `${merged} ${candidate.replace(/^[ \t]+/, "")}`;
|
|
248
304
|
next++;
|
|
249
305
|
if (!leavesCodeSpanOpen(merged)) {
|
|
@@ -261,7 +317,7 @@ function joinWrappedCodeSpans(lines) {
|
|
|
261
317
|
return joined;
|
|
262
318
|
}
|
|
263
319
|
function leavesCodeSpanOpen(text) {
|
|
264
|
-
return text.replace(RE_INLINE_CODE, "").includes(
|
|
320
|
+
return text.replace(RE_INLINE_CODE, "").includes(BACKTICK2);
|
|
265
321
|
}
|
|
266
322
|
var QUOTE_CONVERTERS = {
|
|
267
323
|
markdownToHtml: (markdown) => markdownToTiptap(markdown),
|
|
@@ -276,8 +332,7 @@ function markdownToTiptap(markdown) {
|
|
|
276
332
|
const lines = joinWrappedCodeSpans(html.split("\n"));
|
|
277
333
|
const frontmatterEnd = findFrontmatterEnd(lines);
|
|
278
334
|
const outputBlocks = [];
|
|
279
|
-
let
|
|
280
|
-
let codeBlockLang = "";
|
|
335
|
+
let codeFence = null;
|
|
281
336
|
let codeBlockLines = [];
|
|
282
337
|
const listStack = [];
|
|
283
338
|
let inTable = false;
|
|
@@ -415,26 +470,23 @@ function markdownToTiptap(markdown) {
|
|
|
415
470
|
};
|
|
416
471
|
for (let i = 0; i < lines.length; i++) {
|
|
417
472
|
const line = lines[i];
|
|
418
|
-
if (
|
|
419
|
-
if (
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
flushPendingBlankParagraphs();
|
|
423
|
-
inCodeBlock = true;
|
|
424
|
-
codeBlockLang = line.slice(3).trim();
|
|
473
|
+
if (codeFence) {
|
|
474
|
+
if (isFenceClose(line, codeFence)) {
|
|
475
|
+
pushBlock(fencedCodeToHtml(codeFence, codeBlockLines));
|
|
476
|
+
codeFence = null;
|
|
425
477
|
codeBlockLines = [];
|
|
426
|
-
continue;
|
|
427
478
|
} else {
|
|
428
|
-
|
|
429
|
-
pushBlock(`<pre><code${langAttr}>${escapeHtml(codeBlockLines.join("\n"))}</code></pre>`);
|
|
430
|
-
inCodeBlock = false;
|
|
431
|
-
codeBlockLang = "";
|
|
432
|
-
codeBlockLines = [];
|
|
433
|
-
continue;
|
|
479
|
+
codeBlockLines.push(fenceContentLine(line, codeFence));
|
|
434
480
|
}
|
|
481
|
+
continue;
|
|
435
482
|
}
|
|
436
|
-
|
|
437
|
-
|
|
483
|
+
const fenceOpen = matchFenceOpen(line);
|
|
484
|
+
if (fenceOpen && (fenceOpen.indent === 0 || listStack.length === 0)) {
|
|
485
|
+
flushList();
|
|
486
|
+
flushTable();
|
|
487
|
+
flushPendingBlankParagraphs();
|
|
488
|
+
codeFence = fenceOpen;
|
|
489
|
+
codeBlockLines = [];
|
|
438
490
|
continue;
|
|
439
491
|
}
|
|
440
492
|
if (inTable && !/^\|.*\|$/.test(line.trim())) {
|
|
@@ -524,6 +576,15 @@ function markdownToTiptap(markdown) {
|
|
|
524
576
|
tableLines.push(line);
|
|
525
577
|
continue;
|
|
526
578
|
}
|
|
579
|
+
const linkedImageMatch = line.trim().match(/^\[!\[([^\]]*)\]\(([^()\s]+)\)\]\(([^()\s]+)\)$/);
|
|
580
|
+
if (linkedImageMatch) {
|
|
581
|
+
flushList();
|
|
582
|
+
const alt = escapeHtml(linkedImageMatch[1] ?? "");
|
|
583
|
+
const src = escapeHtml(unwrapLinkDestination(linkedImageMatch[2] ?? ""));
|
|
584
|
+
const href = escapeHtml(unwrapLinkDestination(linkedImageMatch[3] ?? ""));
|
|
585
|
+
pushBlock(`<img alt="${alt}" src="${src}" data-squisq-image-href="${href}">`);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
527
588
|
const standaloneImageMatch = line.trim().match(/^!\[(.*?)\]\((.+?)\)$/);
|
|
528
589
|
if (standaloneImageMatch) {
|
|
529
590
|
flushList();
|
|
@@ -563,9 +624,8 @@ function markdownToTiptap(markdown) {
|
|
|
563
624
|
).join("<br>");
|
|
564
625
|
pushBlock(`<p>${paragraphHtml}</p>`);
|
|
565
626
|
}
|
|
566
|
-
if (
|
|
567
|
-
|
|
568
|
-
pushBlock(`<pre><code${langAttr}>${escapeHtml(codeBlockLines.join("\n"))}</code></pre>`);
|
|
627
|
+
if (codeFence) {
|
|
628
|
+
pushBlock(fencedCodeToHtml(codeFence, codeBlockLines));
|
|
569
629
|
}
|
|
570
630
|
flushList();
|
|
571
631
|
flushTable();
|
|
@@ -608,13 +668,9 @@ function tiptapToMarkdown(html) {
|
|
|
608
668
|
remaining = remaining.slice(headingMatch[0].length);
|
|
609
669
|
continue;
|
|
610
670
|
}
|
|
611
|
-
const codeMatch = remaining.match(/^<pre\b[^>]
|
|
671
|
+
const codeMatch = remaining.match(/^<pre\b([^>]*)><code\b([^>]*)>(.*?)<\/code><\/pre>/s);
|
|
612
672
|
if (codeMatch) {
|
|
613
|
-
|
|
614
|
-
const code = unescapeHtml(codeMatch[2]);
|
|
615
|
-
lines.push("```" + lang);
|
|
616
|
-
lines.push(code);
|
|
617
|
-
lines.push("```");
|
|
673
|
+
lines.push(...fencedCodeToMarkdown(codeMatch[1] ?? "", codeMatch[2] ?? "", codeMatch[3]));
|
|
618
674
|
lines.push("");
|
|
619
675
|
remaining = remaining.slice(codeMatch[0].length);
|
|
620
676
|
continue;
|
|
@@ -718,7 +774,7 @@ function tiptapToMarkdown(html) {
|
|
|
718
774
|
if (src) {
|
|
719
775
|
const alt = /\balt="([^"]*)"/i.exec(attrs)?.[1] ?? "";
|
|
720
776
|
const serialized = serializeImage(src, alt, attrs);
|
|
721
|
-
lines.push(serialized.
|
|
777
|
+
lines.push(serialized.includes("<img") ? serialized : unescapeHtml(serialized));
|
|
722
778
|
lines.push("");
|
|
723
779
|
}
|
|
724
780
|
remaining = remaining.slice(imgMatch[0].length);
|
|
@@ -1037,26 +1093,22 @@ function serializeImage(src, alt, attrs) {
|
|
|
1037
1093
|
const width = /\bwidth="([^"]*)"/i.exec(attrs)?.[1];
|
|
1038
1094
|
const height = /\bheight="([^"]*)"/i.exec(attrs)?.[1];
|
|
1039
1095
|
const title = /\btitle="([^"]*)"/i.exec(attrs)?.[1];
|
|
1096
|
+
const href = /\bdata-squisq-image-href="([^"]*)"/i.exec(attrs)?.[1];
|
|
1097
|
+
const linked = (image) => href ? `[${image}](${escapedDestination(href)})` : image;
|
|
1040
1098
|
if (title?.startsWith("squisq-upload:")) return "";
|
|
1041
1099
|
if (!width && !height) {
|
|
1042
|
-
return `})
|
|
1100
|
+
return linked(`})`);
|
|
1043
1101
|
}
|
|
1044
1102
|
const parts = [`<img alt="${alt}" src="${src}"`];
|
|
1045
1103
|
if (width) parts.push(` width="${width}"`);
|
|
1046
1104
|
if (height) parts.push(` height="${height}"`);
|
|
1047
1105
|
if (title) parts.push(` title="${title}"`);
|
|
1048
1106
|
parts.push(">");
|
|
1049
|
-
return parts.join("");
|
|
1107
|
+
return linked(parts.join(""));
|
|
1050
1108
|
}
|
|
1051
1109
|
function escapedDestination(attrValue) {
|
|
1052
1110
|
return needsAngleDestination(attrValue) ? `<${attrValue}>` : attrValue;
|
|
1053
1111
|
}
|
|
1054
|
-
function escapeHtml(text) {
|
|
1055
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1056
|
-
}
|
|
1057
|
-
function unescapeHtml(text) {
|
|
1058
|
-
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/ | | /gi, "\xA0").replace(/&/g, "&");
|
|
1059
|
-
}
|
|
1060
1112
|
function inlineToHtml(text) {
|
|
1061
1113
|
const placeholders = [];
|
|
1062
1114
|
const stash = (html) => {
|
package/dist/index.js
CHANGED
|
@@ -243,7 +243,7 @@ import {
|
|
|
243
243
|
videoEmbedParagraphJson,
|
|
244
244
|
viewStateFromBinding,
|
|
245
245
|
writeHeadingViewState
|
|
246
|
-
} from "./chunk-
|
|
246
|
+
} from "./chunk-WZONLKTC.js";
|
|
247
247
|
import {
|
|
248
248
|
EditorProvider,
|
|
249
249
|
applySourceEditsToText,
|
|
@@ -264,7 +264,7 @@ import {
|
|
|
264
264
|
useBlockNavigator,
|
|
265
265
|
useEditorContext,
|
|
266
266
|
useEditorInsertMenuItems
|
|
267
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-PCIVTLQG.js";
|
|
268
268
|
import {
|
|
269
269
|
SPEECH_INPUT_SAMPLE_RATE,
|
|
270
270
|
isSpeechInputProviderFactory,
|
|
@@ -273,14 +273,14 @@ import {
|
|
|
273
273
|
import "./chunk-A2H3JOA5.js";
|
|
274
274
|
import {
|
|
275
275
|
JsonEditor
|
|
276
|
-
} from "./chunk-
|
|
276
|
+
} from "./chunk-LDU3AWER.js";
|
|
277
277
|
import {
|
|
278
278
|
MarkdownEscape
|
|
279
|
-
} from "./chunk-
|
|
279
|
+
} from "./chunk-4MBH7MMU.js";
|
|
280
280
|
import {
|
|
281
281
|
markdownToTiptap,
|
|
282
282
|
tiptapToMarkdown
|
|
283
|
-
} from "./chunk-
|
|
283
|
+
} from "./chunk-ZLKINE4Y.js";
|
|
284
284
|
import {
|
|
285
285
|
ImageEditor,
|
|
286
286
|
ImageViewer,
|
package/dist/review/index.js
CHANGED
|
@@ -19,9 +19,9 @@ import {
|
|
|
19
19
|
updateReviewDecorations,
|
|
20
20
|
useReview,
|
|
21
21
|
useReviewState
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-PCIVTLQG.js";
|
|
23
23
|
import "../chunk-DNEVUOBZ.js";
|
|
24
|
-
import "../chunk-
|
|
24
|
+
import "../chunk-ZLKINE4Y.js";
|
|
25
25
|
|
|
26
26
|
// src/review/proofingAdapter.ts
|
|
27
27
|
import {
|
package/dist/shell/index.js
CHANGED
|
@@ -5,16 +5,16 @@ import {
|
|
|
5
5
|
RawEditor,
|
|
6
6
|
WysiwygEditor,
|
|
7
7
|
useEditorContextMenuItems
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-WZONLKTC.js";
|
|
9
9
|
import {
|
|
10
10
|
EditorProvider,
|
|
11
11
|
useEditorContext,
|
|
12
12
|
useEditorInsertMenuItems
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-PCIVTLQG.js";
|
|
14
14
|
import "../chunk-DNEVUOBZ.js";
|
|
15
15
|
import "../chunk-A2H3JOA5.js";
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
16
|
+
import "../chunk-4MBH7MMU.js";
|
|
17
|
+
import "../chunk-ZLKINE4Y.js";
|
|
18
18
|
import "../chunk-HLU6ZBS7.js";
|
|
19
19
|
import "../chunk-LXGQA2SY.js";
|
|
20
20
|
import "../chunk-LRZJD5YD.js";
|
package/dist/styles/index.css
CHANGED
|
@@ -7939,6 +7939,10 @@
|
|
|
7939
7939
|
container-type: inline-size;
|
|
7940
7940
|
container-name: squisq-toolbar;
|
|
7941
7941
|
}
|
|
7942
|
+
.squisq-dialog-portal {
|
|
7943
|
+
font-family: var( --squisq-ux-font, -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif );
|
|
7944
|
+
color: var(--squisq-text);
|
|
7945
|
+
}
|
|
7942
7946
|
.squisq-toolbar-view-tabs {
|
|
7943
7947
|
display: flex;
|
|
7944
7948
|
gap: 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-editor-react",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.7",
|
|
4
4
|
"description": "React editor shell with raw/WYSIWYG/preview modes for Squisq documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -102,12 +102,12 @@
|
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
104
|
"dependencies": {
|
|
105
|
-
"@bendyline/squisq": "2.13.
|
|
105
|
+
"@bendyline/squisq": "2.13.5",
|
|
106
106
|
"@bendyline/squisq-calc": "2.11.2",
|
|
107
|
-
"@bendyline/squisq-formats": "2.8.
|
|
108
|
-
"@bendyline/squisq-grid-react": "2.11.
|
|
109
|
-
"@bendyline/squisq-react": "2.12.
|
|
110
|
-
"@bendyline/squisq-video-react": "2.5.
|
|
107
|
+
"@bendyline/squisq-formats": "2.8.6",
|
|
108
|
+
"@bendyline/squisq-grid-react": "2.11.34",
|
|
109
|
+
"@bendyline/squisq-react": "2.12.14",
|
|
110
|
+
"@bendyline/squisq-video-react": "2.5.15",
|
|
111
111
|
"@fortawesome/fontawesome-free": "7.3.1",
|
|
112
112
|
"@tiptap/core": "2.27.3",
|
|
113
113
|
"@tiptap/extension-heading": "2.27.3",
|